package com.ncmmall.mall.controller.business.marketing;

import com.ncmmall.application.business.marketing.SeckillApplication;
import com.ncmmall.application.securitys.logs.OperationLogApplication;
import com.feijin.commons.exceptions.IllegalRequestException;
import com.feijin.commons.webs.Webs;
import com.ncmmall.domain.business.marketing.seckill.QSeckillSession;
import com.ncmmall.domain.business.marketing.seckill.QSeckillSessionMerchantScope;
import com.ncmmall.domain.business.marketing.seckill.SeckillSession;
import com.ncmmall.domain.business.marketing.seckill.SeckillSessionMerchantScope;
import com.ncmmall.domain.security.user.QWebUser;
import com.ncmmall.domain.security.user.WebUser;
import com.ncmmall.mall.controller.securitys.shiro.Securitys;
import com.ncmmall.mall.params.PageParams;
import com.ncmmall.querychannel.QueryPage;
import com.ncmmall.querychannel.QueryPageRequest;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.primitives.Longs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
 * @author linxs
 * @Description: 秒杀活动场次管理
 * @Date: 2020-01-17 23:13
 */
@Controller
@RequestMapping(value = "/mall/seckillSession")
public class SeckillSessionController {

    private final static Logger logger = LoggerFactory.getLogger(SeckillSessionController.class);

    @Autowired
    private QueryChannelService queryChannelService;

    @Autowired
    private SeckillApplication seckillSessionApplication;

    @Autowired
    private OperationLogApplication logApplication;

    /**
     * 特价活动管理
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    private String list(Model model, PageParams pageParams, SeckillSession seckill) {
        QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageParams.getPageNo());
        Map<String, Object> params = Maps.newHashMap();
        String hql = builderSQL("select u from SeckillSession u where 1 = 1 ", params, seckill);
        QueryPage<SeckillSession> page = queryChannelService.findPage(hql, pageRequest.setParams(params), SeckillSession.class);

        model.addAttribute("page", page).addAttribute("params", seckill);

        return "mall/marketing/seckill/session/list";
    }

    /**
     * 详情
     */
    @RequestMapping(value = "/{id}/detail", method = RequestMethod.GET)
    private String detail(Model model, @PathVariable("id") long id) {

        model.addAttribute("seckillSession", queryChannelService.findOne(QSeckillSession.seckillSession.id.eq(id), SeckillSession.class)).addAttribute("merchants", queryChannelService.findAll(QSeckillSessionMerchantScope.seckillSessionMerchantScope.seckillSession.id.eq(id), SeckillSessionMerchantScope.class)).addAttribute("_method", "PUT");

        return "mall/marketing/seckill/session/detail";

    }

    /**
     * 添加秒杀场次页面
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/create", method = RequestMethod.GET)
    private String create(Model model) {

        model.addAttribute("seckillSession", new SeckillSession()).addAttribute("_method", "POST");

        return "mall/marketing/seckill/session/form";
    }

    /**
     * 添加秒杀场次
     */
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    private Map<String, Object> create(HttpServletRequest request, @RequestHeader("X-Requested-With") String requestWith, @ModelAttribute SeckillSession seckillSession) {
        try {

            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be ajax !");
            }

            seckillSessionApplication.createSeckillSession(seckillSession);
            logApplication.eventOfSystem(Securitys.currentUser(), "添加秒杀场次" + seckillSession.getName(), Securitys.getIp(request));

        } catch (Exception e) {
            logger.error("[添加秒杀场次异常]", e);
            return ImmutableMap.of("status", false, "message", "添加秒杀场次异常");
        }

        return ImmutableMap.of("status", true);
    }

    /**
     * 编辑
     *
     * @param model
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}/modify", method = RequestMethod.GET)
    private String modify(Model model, @PathVariable("id") long id) {
        model.addAttribute("seckillSession", queryChannelService.findOne(QSeckillSession.seckillSession.id.eq(id), SeckillSession.class)).addAttribute("merchants", queryChannelService.findAll(QSeckillSessionMerchantScope.seckillSessionMerchantScope.seckillSession.id.eq(id), SeckillSessionMerchantScope.class)).addAttribute("_method", "PUT");

        return "mall/marketing/seckill/session/form";
    }

    /**
     * 编辑秒杀场次
     *
     * @param request
     * @param requestWith
     * @param seckillSession
     * @return
     */
    @RequestMapping(value = "/{id}/modify", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> modify(HttpServletRequest request, @RequestHeader("X-Requested-With") String requestWith, @ModelAttribute SeckillSession seckillSession) {
        try {

            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be ajax !");
            }

            seckillSessionApplication.modifySeckillSession(seckillSession);
            logApplication.eventOfSystem(Securitys.currentUser(), "编辑秒杀场次" + seckillSession.getName(), Securitys.getIp(request));

        } catch (Exception e) {
            logger.error("[编辑秒杀场次异常]", e);
            return ImmutableMap.of("status", false, "message", "编辑秒杀场次异常");
        }

        return ImmutableMap.of("status", true);
    }

    /**
     * 下架秒杀场次
     *
     * @param request
     * @param requestWith
     * @param seckillSession
     * @return
     */
    @RequestMapping(value = "/soldOut", method = RequestMethod.PUT)
    @ResponseBody
    public Map<String, Object> soldOut(HttpServletRequest request, @RequestHeader("X-Requested-With") String requestWith, SeckillSession seckillSession) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalArgumentException("request must be ajax");
            }

            seckillSessionApplication.soldOutSeckillSession(seckillSession.getId());
            logApplication.eventOfSystem(Securitys.currentUser(), "下架秒杀场次", Securitys.getIp(request));
            return ImmutableMap.of("status", true, "message", "下架成功");

        } catch (Exception e) {

            logger.error("秒杀场次下架异常", e);
            return ImmutableMap.of("status", false, "message", "下架异常");

        }
    }

    /**
     * 上架秒杀场次
     *
     * @param request
     * @param requestWith
     * @param seckillSession
     * @return
     */
    @RequestMapping(value = "/putaway", method = RequestMethod.PUT)
    @ResponseBody
    public Map<String, Object> putaway(HttpServletRequest request, @RequestHeader("X-Requested-With") String requestWith, SeckillSession seckillSession) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalArgumentException("request must be ajax");
            }

            seckillSessionApplication.putawaySeckillSession(seckillSession.getId());
            logApplication.eventOfSystem(Securitys.currentUser(), "上架秒杀场次", Securitys.getIp(request));
            return ImmutableMap.of("status", true, "message", "上架成功");

        } catch (Exception e) {

            logger.error("秒杀场次上架异常", e);
            return ImmutableMap.of("status", false, "message", "上架异常");

        }
    }

    /**
     * 选择商家
     *
     * @param model
     * @param pageParams
     * @param merchant
     * @return
     */
    @RequestMapping(value = "/chooseMerchants", method = RequestMethod.GET)
    private String chooseMerchants(Model model, PageParams pageParams, WebUser merchant) {
        QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageParams.getPageNo());
        Map<String, Object> params = Maps.newHashMap();
        String hql = builderMerchantsSQL("select u from WebUser u where u.role.name = 'MERCHANT'  ", params, merchant);
        QueryPage<WebUser> page = queryChannelService.findPage(hql, pageRequest.setParams(params), WebUser.class);

        model.addAttribute("page", page).addAttribute("params", merchant);

        return "mall/marketing/seckill/session/chooseMerchants";
    }

    /**
     * 查询商城
     *
     * @param ids
     * @return
     */
    @RequestMapping(value = "/queryMerchants", method = RequestMethod.GET)
    @ResponseBody
    private Map<String, Object> queryMerchants(@RequestParam("ids") String ids) {

        List<WebUser> members = Lists.transform(Splitter.on("-").omitEmptyStrings().trimResults().splitToList(ids), new Function<String, WebUser>() {
            @Nullable
            @Override
            public WebUser apply(@Nullable String input) {
                return queryChannelService.findOne(QWebUser.webUser.id.eq(Longs.tryParse(input)), WebUser.class);
            }
        });

        return ImmutableMap.of("status", true, "members", members);

    }

    private String builderMerchantsSQL(String sql, Map<String, Object> params, WebUser merchant) {
        if (!Strings.isNullOrEmpty(merchant.getRealName())) {
            sql += " and u.realName like :realname ";
            params.put("realname", "%" + merchant.getRealName() + "%");
        }

        if (!Strings.isNullOrEmpty(merchant.getMobile())) {
            sql += " and u.mobile like :mobile ";
            params.put("mobile", "%" + merchant.getMobile() + "%");
        }

        if (!Strings.isNullOrEmpty(merchant.getUsername())) {
            sql += " and u.username like :username ";
            params.put("username", "%" + merchant.getUsername() + "%");
        }

        if (!Strings.isNullOrEmpty(merchant.getShopName())) {
            sql += " and u.shopName like :shopname ";
            params.put("shopname", "%" + merchant.getShopName() + "%");
        }

        if (merchant.getMainType() > 0) {
            sql += " and u.mainType = :maintype ";
            params.put("maintype", merchant.getMainType());
        }

        if (!Strings.isNullOrEmpty(merchant.getOrderByGoodsNumber())) {
            sql += " order by u.goodsNumber " + merchant.getOrderByGoodsNumber();
        }

        if (!Strings.isNullOrEmpty(merchant.getOrderByMerchantEnterTime())) {
            sql += " order by u.merchantEnterTime " + merchant.getOrderByMerchantEnterTime();
        }

        if (!Strings.isNullOrEmpty(merchant.getOrderByTotalOrderAmount())) {
            sql += " order by u.totalOrderAmount " + merchant.getOrderByTotalOrderAmount();
        }

        if (!Strings.isNullOrEmpty(merchant.getOrderByTotalOrderNumber())) {
            sql += " order by u.totalOrderNumber " + merchant.getOrderByTotalOrderNumber();
        }

        return sql;
    }

    /**
     * 条件筛选
     */
    private String builderSQL(String sql, Map<String, Object> params, SeckillSession seckill) {

        if (!Strings.isNullOrEmpty(seckill.getName())) {
            sql += " and u.name like :name ";
            params.put("name", "%" + seckill.getName() + "%");
        }

        if (!Strings.isNullOrEmpty(seckill.getSeckillBeginTime())) {
            sql += " and u.seckillTime >= :begintime ";
            params.put("begintime", seckill.getSeckillBeginTime());
        }

        if (!Strings.isNullOrEmpty(seckill.getSeckillEndTime())) {
            sql += " and u.seckillTime <= :endtime ";
            params.put("endtime", seckill.getSeckillEndTime());
        }

        if (seckill.getStatus() > 0) {
            sql += " and u.status = :status ";
            params.put("status", seckill.getStatus());
        }

        if (seckill.getIsValidity() > 0) {
            sql += " and u.isValidity = :isValidity ";
            params.put("isValidity", seckill.getIsValidity());
        }

        sql += " order by u.createTime desc ";

        return sql;
    }

}
